package com.gravata.enigma.reader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;

import com.gravata.enigma.FtpHelper;
import com.gravata.enigma.PublishMessage;
import com.gravata.enigma.R;
import com.gravata.enigma.activities.TelaInicial;
import com.gravata.enigma.model.Service;
import com.gravata.enigma.model.Transponder;

public class ParseLameDb {
	private static int lame_type=4;
	private static Map<String,TransponderTmp> transponderTmps;
	private static PublishMessage listener;

	public static void parse(Context context,PublishMessage listener){
		ParseLameDb.listener=listener;

		FtpHelper ftpHelper=new FtpHelper(context);

		try {
			ftpHelper.connect();
		} catch (Exception e1) {
			listener.publish(context.getString(R.string.ftp_error_conexao));
			try {
				Thread.sleep(4000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return ;
		}
		ParseLameDb.listener.publish(context.getString(R.string.parse_lamedb_lendo_arquivo));

        InputStream in = ftpHelper.getFileStream(TelaInicial.profile.getLamePath());

        InputStreamReader is = new InputStreamReader(in);
        StringBuilder sb=new StringBuilder();
        BufferedReader br = new BufferedReader(is);
		try {
			int i=0;
			String read = br.readLine();
			 while(read != null) {

		            sb.append(read).append(System.getProperty("line.separator"));
		            if(i==0){
		            	Matcher matcher= Pattern.compile("\\d").matcher(read);
		            	matcher.find();
		            	if(matcher.groupCount()>0){
		            		lame_type=Integer.parseInt(matcher.group());
		            	}
		            }
		            read =br.readLine();
		            i++;
		        }
		} catch (IOException e) {
			e.printStackTrace();
		}


        String lameDB=sb.toString();
        transponderTmps=parseTransponders(lameDB);
        try {
			TelaInicial.repositorioService.excluir(TelaInicial.repositorioService.listar(TelaInicial.profile));
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
        if(transponderTmps.size()>0){
        	parseServices(lameDB);

        	Set<String> keys=transponderTmps.keySet();
        	for(String key: keys){

        		TransponderTmp tmpT=transponderTmps.get(key);
        		Transponder transponder= TelaInicial.repositorioTransponder.getTransponder(TelaInicial.profile, tmpT.position, tmpT.freq, tmpT.symbol, tmpT.polarization);
        		if(transponder!=null){
        			for(Service service:tmpT.services){
        				service.setTransponder(transponder);
        				service.setProfile(TelaInicial.profile);
        				try {
        		    		ParseLameDb.listener.publish(context.getString(R.string.parse_lamedb_inserindo_servico)+ " "+service.getName());

							TelaInicial.repositorioService.inserir(service);
						} catch (SQLException e) {
							e.printStackTrace();
						}
        			}
        		}
        	}

        }

        ftpHelper.disconnect();

	}

	private static Map<String,TransponderTmp> parseTransponders(String lameDB){

		Map<String,TransponderTmp> transponderTmps=new HashMap<String, ParseLameDb.TransponderTmp>();

		Pattern pattern= Pattern.compile("(?<=(transponders))[\\s\\S]+\\/(?=\\s(end))",Pattern.DOTALL);
		Matcher matcher= pattern.matcher(lameDB);
		matcher.find();
		//pega todas as transponders
		if(matcher.groupCount()>0){
			String strTransponder=matcher.group();
			pattern= Pattern.compile("[^/]*",Pattern.DOTALL);
			Matcher m1= pattern.matcher(strTransponder);
			//separa as tps
			while(m1.find()){
				String linha=m1.group().replaceAll("\n", "#");
				if(!linha.isEmpty()){
					linha=linha.substring(1, linha.length()-1);

					String [] tpItem=linha.split("#");

					String [] match=tpItem[1].split(":");

					//11175000:28887000:0:3:-610:2:0

					//11884000:15000000:0:2:-610:2:0:1:2:0:2
					//freq:symbol:pol:fec:sat:inversion:flags:system:Modulation:Rolloff:pilot

					TransponderTmp transponderTmp=new TransponderTmp();
					transponderTmp.id=tpItem[0].trim();
					transponderTmp.freq=Integer.parseInt(match[0].replaceAll("\\D", ""));
					transponderTmp.symbol=Integer.parseInt(match[1]);
					transponderTmp.polarization=Integer.parseInt(match[2]);
					transponderTmp.fec=Integer.parseInt(match[3]);
					transponderTmp.position=Integer.parseInt(match[4]);
					transponderTmp.inversion=Integer.parseInt(match[5]);

					if(lame_type==4){
						transponderTmp.flags=Integer.parseInt(match[6]);


						try{
							transponderTmp.system=Integer.parseInt(match[7]);
						}catch(ArrayIndexOutOfBoundsException e){
							transponderTmp.system=0;
						}

						try{
							transponderTmp.modulation=Integer.parseInt(match[8]);
						}catch(ArrayIndexOutOfBoundsException e){
							transponderTmp.modulation=0;
						}

						if(transponderTmp.system==1){
							try{
								transponderTmp.rolloff=Integer.parseInt(match[9]);
							}catch(ArrayIndexOutOfBoundsException e){
								transponderTmp.rolloff=0;
							}
							try{
								transponderTmp.pilot=Integer.parseInt(match[10]);
							}catch(ArrayIndexOutOfBoundsException e){
								transponderTmp.pilot=0;
							}

						}

					}else{

						try{
							transponderTmp.system=Integer.parseInt(match[6]);
						}catch(ArrayIndexOutOfBoundsException e){
							transponderTmp.system=0;
						}

						try{
							transponderTmp.modulation=Integer.parseInt(match[7]);
						}catch(ArrayIndexOutOfBoundsException e){
							transponderTmp.modulation=0;
						}

						if(transponderTmp.system==1){
							try{
								transponderTmp.rolloff=Integer.parseInt(match[8]);
							}catch(ArrayIndexOutOfBoundsException e){
								transponderTmp.rolloff=0;
							}
							try{
								transponderTmp.pilot=Integer.parseInt(match[9]);
							}catch(ArrayIndexOutOfBoundsException e){
								transponderTmp.pilot=0;
							}

						}
					}

					transponderTmps.put(transponderTmp.id, transponderTmp);
				}
			}
		}
		return transponderTmps;

	}


	private static void parseServices(String lameDB){

		List<Service> servicesTmps=new ArrayList<Service>();

		Pattern pattern= Pattern.compile("p:.*\\s.*\\s.*");
		Matcher matcher= pattern.matcher(lameDB);
		int i=0;
		while(matcher.find()){

			String [] linha= matcher.group().split("\n");
			if(linha.length>0){
				String provider=linha[0];
				//0010:0bae2b2f:0007:0001:0:0
				String [] serviceInfo=linha[1].split(":");


				String sid=serviceInfo[0];
				if(serviceInfo.length==1)
					break;
				int tipo=Integer.parseInt(serviceInfo[4]);

				if(tipo!=1 && tipo!=25)
					continue;
				String tpId=serviceInfo[1]+":"+serviceInfo[2]+":"+serviceInfo[3];
				String nome="";

				try{
					nome=linha[2];
				}catch(ArrayIndexOutOfBoundsException e){
					nome="";
				}

				Service service=new Service();
				service.setSid(sid);
				service.setName(nome);
				service.setType(tipo);
				service.setReference(getReferense(serviceInfo, nome));

				transponderTmps.get(tpId).services.add(service);
			}
		}

	}


	private static class TransponderTmp{
		String id;
		int freq,symbol,polarization,fec,position,inversion,flags,system,modulation,rolloff,pilot;
		List<Service> services=new ArrayList<Service>();
	}

	private static String getReferense(String [] info,String nome){
		//014f:0bae2b57:000d:0001:1:0
		//0321:0baeabd6:001c:0001:25:0
		//#SERVICE 1:0:1:14F:D:1:BAE2B57:0:0:0::+ Globosat
		//#SERVICE 1:0:19:321:1C:1:BAEABD6:0:0:0::+ Globosat HD

		String sid= info[0].replaceFirst ("^0*", "");
		String namespace=info[1].replaceFirst ("^0*", "");
		String streamid=info[2].replaceFirst ("^0*", "");
		String network=info[3].replaceFirst ("^0*", "");
		int tipo=Integer.parseInt(info[4]);

		return ("#SERVICE 1:0:"+(tipo==25?"19:":"1:")+sid+":"+streamid+":"+network+":"+namespace+":0:0:0::").toUpperCase()+nome;
	}
}
